home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / man2html-2.0.2 / install.me < prev    next >
Text File  |  1995-06-18  |  20KB  |  566 lines

  1. #! /usr/local/bin/perl
  2. ##---------------------------------------------------------------------------##
  3. ##  File:
  4. ##      install.me (for man2html)
  5. ##  Author:
  6. ##      Earl Hood       ehood@convex.com
  7. ##  Description:
  8. ##      Configurable installation program.
  9. ##    Just edit the variables in the CONFIG section.
  10. ##  To Do:
  11. ##    o Add support for manpages to go in different section directories.
  12. ##
  13. ##---------------------------------------------------------------------------##
  14. ##  Copyright (C) 1994  Earl Hood, ehood@convex.com
  15. ##
  16. ##  This program is free software; you can redistribute it and/or modify
  17. ##  it under the terms of the GNU General Public License as published by
  18. ##  the Free Software Foundation; either version 2 of the License, or
  19. ##  (at your option) any later version.
  20. ##  
  21. ##  This program is distributed in the hope that it will be useful,
  22. ##  but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. ##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. ##  GNU General Public License for more details.
  25. ##  
  26. ##  You should have received a copy of the GNU General Public License
  27. ##  along with this program; if not, write to the Free Software
  28. ##  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29. ##---------------------------------------------------------------------------##
  30. ###############################################################################
  31. package main;
  32.  
  33. ##---------------------------------------------------------------------------
  34. ##    Begin CONFIG section
  35. ##
  36. umask 022;    # Set umask
  37.  
  38. ## Set flags
  39. $dobin = 1;    # Set to 1 if exectuables to install
  40. $dolib = 0;    # Set to 1 if libraries to install
  41. $dodoc = 1;    # Set to 1 if documents to install
  42.  
  43. ## Set default values
  44. $bindir  = '/usr/local/bin';
  45. $libdir  = '/usr/local/lib/perl';
  46. $docdir  = '/usr/local/lib/doc';
  47. $perlprg = '/usr/local/bin/perl';
  48.  
  49. ## Set files to install
  50. $relbin = '.';       # Location of source bin files relative to install.me
  51. @binfiles = (
  52.     "man2html",
  53. );
  54. $rellib = 'lib';    # Location of source lib files relative to install.me
  55. @libfiles = (
  56. );
  57. $reldoc = 'doc';    # Location of source doc files relative to install.me
  58. @docfiles = (
  59.     "man2html.doc.html",
  60. );
  61.  
  62. ## Print intro text
  63. print STDOUT <<EndofIntro;
  64. man2html Installation
  65. ==============================================
  66. The installation process will ask you a series of questions on where
  67. the Perl executable is and where to put man2html.  Just hit <CR> to
  68. accept the default values listed in ()'s.
  69.  
  70. EndofIntro
  71. ##
  72. ##    End CONFIG section
  73. ##---------------------------------------------------------------------------
  74. ##---------------------------------------------------------------------------
  75. ##    Main routine
  76. ##---------------------------------------------------------------------------
  77. {
  78. { package uio;
  79.     @LastText = ();    ## Cached text
  80.     $use_handler = 1;    ## Flag to use private CONT signal handler
  81.     $ext_sigcont;    ## External CONT handler
  82. }
  83.  
  84. &print_note("Make sure all pathnames are absolute.");
  85. &pause();
  86.  
  87. ## Get installation directories and path to Perl
  88. while (1) {
  89.     $tmp = &prompt_user_def("Perl executable", $perlprg, 0, 1);
  90.     last if -x $tmp;
  91.     print STDERR "$tmp not executable\n";
  92. }
  93. $perlprg = $tmp;
  94. if ($dobin) {
  95.     do {
  96.     $tmp = &prompt_user_def("Location to install programs",
  97.                  $bindir, 0, 1);
  98.     } while (!&create_dir($tmp));
  99.     $bindir = $tmp;
  100. }
  101. if ($dolib) {
  102.     do {
  103.     $tmp = &prompt_user_def("Location to install libraries",
  104.                 $libdir, 0, 1);
  105.     } while (!&create_dir($tmp));
  106.     $libdir = $tmp;
  107. }
  108. if ($dodoc) {
  109.     if (&ask_question("Install documentation", 1)) {
  110.     do {
  111.         $tmp = &prompt_user_def("Location to install docs",
  112.                     $docdir, 0, 1);
  113.     } while (!&create_dir($tmp));
  114.     $docdir = $tmp;
  115.     } else {
  116.     $dodoc = 0;
  117.     }
  118. }
  119. $perlprg = "#! $perlprg\n";
  120. $perlprg .= "unshift(\@INC, '$libdir');\n"  if $dolib;
  121.  
  122. if ($dobin && @binfiles) {
  123.     print STDOUT "Installing the following into $bindir\n";
  124.     foreach $file (@binfiles) {
  125.     print STDOUT "\t", $file, "\n";
  126.     &cp("$relbin/$file", "$bindir/$file", $perlprg);
  127.     chmod 0755, "$bindir/$file";
  128.     }
  129. }
  130. if ($dolib && @libfiles) {
  131.     print STDOUT "Installing the following into $libdir\n";
  132.     foreach $file (@libfiles) {
  133.     print STDOUT "\t", $file, "\n";
  134.     &cp("$rellib/$file", "$libdir/$file");
  135.     }
  136. }
  137. if ($dodoc && @docfiles) {
  138.     print STDOUT "Installing the following into $docdir\n";
  139.     foreach $file (@docfiles) {
  140.     print STDOUT "\t", $file, "\n";
  141.     &cp("$reldoc/$file", "$docdir/$file");
  142.     }
  143. }
  144.  
  145. exit 0;
  146. }
  147. ##---------------------------------------------------------------------------
  148. ##    Main subroutines
  149. ##---------------------------------------------------------------------------
  150. sub create_dir {
  151.     local($d) = shift;
  152.     local(@a) = grep($_ ne '', split(/\//, $d));
  153.     local($path, $dir);
  154.  
  155.     if ($d =~ /^\s*\//) {
  156.     $path = '';
  157.     } else {
  158.     $path = '.';
  159.     }
  160.     foreach $dir (@a) {
  161.     if (! -e "$path/$dir") {
  162.         if (!mkdir("$path/$dir", 0777)) {
  163.         print STDERR "Unable to create $path/$dir: $!\n";
  164.         return 0;
  165.         }
  166.     } elsif (! -d "$path/$dir") {
  167.         print STDERR "$dir is not a directory\n";
  168.         return 0;
  169.     }
  170.     $path .= '/' . $dir;
  171.     }
  172.     if (! -w $d) {
  173.     print STDERR "$d not writable\n";
  174.     return 0;
  175.     }
  176.     1;
  177. }
  178. ##---------------------------------------------------------------------------
  179. sub cp {
  180.     local($src, $dst, $prepend) = @_;
  181.     open(SRC, $src) || die "Unable to open $src: $!\n";
  182.     open(DST, "> $dst") || die "Unable to create $dst: $!\n";
  183.     if ($prepend) {
  184.     print DST $prepend;
  185.     }
  186.     print DST <SRC>;
  187.     close(SRC);
  188.     close(DST);
  189. }
  190.  
  191.  
  192. ###############################################################################
  193. package uio;
  194.  
  195. ##---------------------------------------------------------------------------##
  196. ##  The following routines are defined in this package.  All routines
  197. ##  work off of STDOUT.
  198. ##    sub main'ask_question        -- ask yes/no question
  199. ##    sub main'do_num_menu        -- autonumber menu items & print
  200. ##    sub main'flush            -- flush filehandle
  201. ##    sub main'get_char_choice    -- get char that is in list
  202. ##    sub main'get_later_date        -- Get date later than some date
  203. ##    sub main'get_lc_string        -- get string converted to lowercase
  204. ##    sub main'get_string        -- get string
  205. ##    sub main'pause            -- pause until <CR> hit
  206. ##    sub main'print_error        -- print error message
  207. ##    sub main'print_info        -- print information message
  208. ##    sub main'print_menu        -- print a menu to screen
  209. ##    sub main'print_note        -- print note message
  210. ##    sub main'print_warning        -- print warning message
  211. ##    sub main'prompt_user        -- prompt user for string
  212. ##    sub main'prompt_user_def    -- prompt_user() with default value
  213. ##
  214. ##  Private routines.
  215. ##    sub handler            -- private SIGCONT handler
  216. ##    sub print_message         -- print typed message to screen
  217. ##    sub print_txt            -- print text and cache it
  218. ##    sub reset_handler        -- unregister handler()
  219. ##    sub set_handler            -- register handler()
  220. ##
  221. ##  Notes:
  222. ##    For the pause() and prompt_user*() routines, a signal handler
  223. ##    is registered to handle the SIGCONT signal.  This enables the
  224. ##    routines to redisplay the prompt after the program has been
  225. ##    suspended and continued while prompting the user for input.
  226. ##    The handler has to redisplay the text, therefore the mentioned
  227. ##    routines use the print_txt() for caching the prompt text.
  228. ##
  229. ##    When the signal handler is registered, any existing handler for
  230. ##    SIGCONT is stored and is called first before redisplaying the
  231. ##    cached text.  Uio's signal handler can be disabled if the
  232. ##    variable $uio'use_handler is set to zero.  By default, the
  233. ##    value is one.  More inforamtion is below in the various
  234. ##    subroutine descriptions.
  235. ##---------------------------------------------------------------------------##
  236.                 ##------------------##
  237.                 ## Global variables ##
  238.                 ##------------------##
  239. ##---------------------------------------------------------------------------
  240. @LastText = ();        ## Cached text
  241. $use_handler = 1;    ## Flag to use private CONT signal handler
  242. $ext_sigcont;        ## External CONT handler
  243. ##---------------------------------------------------------------------------
  244.             ##---------------------------------##
  245.             ## Private subroutine declerations ##
  246.             ##---------------------------------##
  247. ##---------------------------------------------------------------------------
  248. ##    print_txt() prints @_ to STDOUT.  It also makes a copy of @_ to
  249. ##    an array called @LastText.  Any outside package can access it
  250. ##    using uio'LastText.  This is useful for redisplaying text
  251. ##    after the program has been suspended and continued.
  252. ##
  253. sub print_txt {
  254.     print STDOUT @_;  @LastText = @_;
  255. }
  256. ##---------------------------------------------------------------------------
  257. ##    This routine is used by print_{error, info, note, warning}
  258. ##    routines to output an informitive message to STDOUT.
  259. ##
  260. sub print_message {
  261.     local($type, $mesg) = ($_[0], join("", @_[1 .. $#_]));
  262.     local($head) = sprintf("    %9s", "$type  ");
  263.     local($indent) = " " x 13;
  264.     local($i, $dashes, @array);
  265.  
  266.     @array = split(/\n/, $mesg);
  267.     foreach (@array) { $i = length($_)  if length($_) > $i; }
  268.     $dashes = " " x 4 . "-" x ($i+10);
  269.     $mesg = join("\n", @array);
  270.     $* = 1;
  271.     $mesg =~ s/\n/\n$indent/g;
  272.     $mesg = $head . $mesg;
  273.     print STDOUT "$dashes\n", "$mesg\n", "$dashes\n";
  274.     $* = 0;
  275. }
  276. ##---------------------------------------------------------------------------
  277. ##    handler() is the private signal handler for the uio package.
  278. ##    It's used to when SIGCONT is caught for redisplay cached text.
  279. ##    The external handler is called if defined.
  280. ##
  281. sub handler {
  282.     if ($ext_sigcont ne 'IGNORE' && $ext_sigcont ne 'DEFAULT' &&
  283.     $ext_sigcont ne "") { &$ext_sigcont(@_); }
  284.     print STDOUT @LastText;
  285.     &'flush(STDOUT);
  286.     push(@Redo, 1);
  287. }
  288. ##---------------------------------------------------------------------------
  289. ##    set_handler() sets the private CONT signal handler.
  290. ##
  291. sub set_handler {
  292.     return unless $use_handler;
  293.     $ext_sigcont = $SIG{'CONT'};
  294.     $SIG{'CONT'} = "uio'handler";
  295. }
  296. ##---------------------------------------------------------------------------
  297. ##    reset_handler() restores the external handler
  298. ##
  299. sub reset_handler {
  300.     return unless $use_handler;
  301.     $SIG{'CONT'} = $ext_sigcont;
  302. }
  303. ##---------------------------------------------------------------------------
  304.             ##--------------------------------##
  305.             ## Public subroutine declerations ##
  306.             ##--------------------------------##
  307. ##---------------------------------------------------------------------------
  308. ##    print_menu() a tabular list of items in a "menu" type format.  The
  309. ##    list is printed in column major order.
  310. ##    Parameters:
  311. ##        $title    : The title of the menu if not null.
  312. ##        $cols    : Number of columns in menu.
  313. ##        $box    : Boolean flag for drawing a box around menu.
  314. ##        $sep    : Separator string between columns.
  315. ##        @menu_items    : Array of menu items.
  316. ##    In box mode the title appears above the box.  Care must be taken
  317. ##    in the number of columns chosen when menu items string lengths get
  318. ##    long.  This routine assumes there is plenty of screen space to
  319. ##    print out the menu.
  320. ##
  321. sub main'print_menu {
  322.     local($title, $cols, $box, $sep, @menu_items) = @_;
  323.     local($i, $j, $indent, $sp, $fmt, $lside, $rside);
  324.  
  325.     $sp = " ";  $indent = $sp x 8;
  326.     foreach (@menu_items) { $i = length($_)  if length($_) > $i; }
  327.     $fmt = "%-${i}s";
  328.     $dashes = "-" x (($cols-1)*length($sep) + $cols*$i + 2);
  329.     $lines = ($#menu_items+1)/$cols;
  330.     $lines = ($lines == int($lines) ? $lines : int($lines)+1);
  331.     print STDOUT "$indent$title\n"  if $title ne "";    ## Print $title
  332.     print STDOUT "$indent $dashes\n"  if $box;        ## Print top of box
  333.     $lside = ($box ? "| " : "  ");
  334.     $rside = ($box ? " |\n" : "  \n");
  335.     for ($i=0; $i < $lines; $i++) {
  336.     print STDOUT $indent, $lside;
  337.     for ($j=0; $j < $cols; $j++) {
  338.         print STDOUT sprintf($fmt, $menu_items[$i + $j*$lines]);
  339.         print STDOUT $sep  if $j < $cols-1;
  340.     }
  341.     print STDOUT $rside;
  342.     }
  343.     print STDOUT "$indent $dashes\n" if $box;
  344. }
  345. ##---------------------------------------------------------------------------
  346. ##    do_num_menu() automatically generates a numbered list of items
  347. ##    for selection.  The routine returns the string item that is
  348. ##    selected.  This routine also appends a "Other" option and
  349. ##    if selected, will prompt for a user defined string.
  350. ##
  351. sub main'do_num_menu {
  352.     local($title, $prompt, $isother, $otherprompt, $otherdef, $cols,
  353.       @array) = @_;
  354.     local(@menu_items) = @array;
  355.     local($i, $tmp);
  356.  
  357.     ## Prepend numbers to items ##
  358.     for ($i=0; $i <= $#menu_items; $i++) {
  359.         $menu_items[$i] = $i+1 . " = \"$menu_items[$i]\"";
  360.     }
  361.     ## Add other selection if needed ##
  362.     push(@menu_items, $i+1 . " = Other")  if $isother;
  363.     ## Print menu ##
  364.     print STDOUT "\n$title:\n\n";
  365.     &'print_menu("", $cols, 0, " " x 5, @menu_items);
  366.     ## Get selection ##
  367.     while (1) {
  368.     $tmp = &'prompt_user_def("\n$prompt", "1", 0, 0);
  369.     last  if ($tmp >= 1 && $tmp <= $#menu_items+1);
  370.     &'print_error("Invalid selection -- $tmp");
  371.     }
  372.     ## Determine selection ##
  373.     if ($isother && $tmp == $#menu_items+1) {
  374.         $tmp = &'prompt_user_def("  Other: $otherprompt", $otherdef, 1, 0);
  375.     }
  376.     else { $tmp = $array[$tmp-1]; }
  377.     $tmp;
  378. }
  379. ##---------------------------------------------------------------------------
  380. ##     print_*() routines to print a message of type '*' to the screen.
  381. ##
  382. sub main'print_error { &print_message("ERROR", @_); }
  383. sub main'print_info { &print_message("Info:", @_); }
  384. sub main'print_note { &print_message("Note:", @_); }
  385. sub main'print_warning { &print_message("WARNING", @_); }
  386. ##---------------------------------------------------------------------------
  387. ##    Get string from STDIN and lowercase it.
  388. ##    called "get_lc_string".
  389. ##
  390. sub main'get_lc_string {
  391.     local($tmp);
  392.     $tmp = <STDIN>;
  393.     while (shift(@Redo)) { $tmp = <STDIN>; }
  394.     chop $tmp;
  395.     $tmp =~ tr/A-Z/a-z/;
  396.     $tmp;
  397. }
  398. ##---------------------------------------------------------------------------
  399. ##    Get string from STDIN.
  400. ##
  401. sub main'get_string {
  402.     local($tmp);
  403.     $tmp = <STDIN>;
  404.     while (shift(@Redo)) { $tmp = <STDIN>; }
  405.     chop $tmp;
  406.     $tmp;
  407. }
  408. ##---------------------------------------------------------------------------
  409. ##    Pause output until CR is hit.
  410. ##
  411. sub main'pause {
  412.     &set_handler();
  413.     local($tmp);
  414.     &print_txt("\nHit <CR> to continue ... ");
  415.     $tmp = <STDIN>;
  416.     while (shift(@Redo)) { $tmp = <STDIN>; }
  417.     &reset_handler();
  418. }
  419. ##---------------------------------------------------------------------------
  420. ##    Prompt user for a string of input.  This routine appends a "->"
  421. ##    to the prompt string.  All leading and trailing whitespaces are
  422. ##    removed from the input string before returned.
  423. ##
  424. sub main'prompt_user {
  425.     &set_handler();
  426.     local($prompt, $nonnull, $return) = @_;
  427.     local($tmp);
  428.     $prompt .= "\n" if $return;
  429.     $prompt .= " -> ";
  430.     while (1) {
  431.     &print_txt($prompt);
  432.     $tmp = &'get_string();
  433.     &'print_error("Entry cannot be blank."), next
  434.         if $nonnull && $tmp =~ /^\s*$/;
  435.     $tmp =~ s/^\s*(.*[^\s])\s*$/\1/;  ## strip beginning/trailing spaces
  436.     last;
  437.     }
  438.     &reset_handler();
  439.     $tmp;
  440. }
  441. ##---------------------------------------------------------------------------
  442. ##    Like prompt_user() but a default choice is given.
  443. ##
  444. sub main'prompt_user_def {
  445.     &set_handler();
  446.     local($prompt, $default, $nonnull, $return) = @_;
  447.     local($tmp);
  448.     $prompt .= " (\"$default\")";
  449.     $prompt .= "\n" if $return;
  450.     $prompt .= " -> ";
  451.     while(1) {
  452.     &print_txt($prompt);
  453.     $tmp = &'get_string();
  454.     $tmp = $default  if $tmp =~ m/^\s*$/;
  455.     &'print_error("Entry cannot be blank."), next
  456.         if $nonnull && $tmp =~ /^\s*$/;
  457.     $tmp =~ s/^\s*(.*[^\s])\s*$/\1/;
  458.     last;
  459.     }
  460.     &reset_handler();
  461.     $tmp;
  462. }
  463. ##---------------------------------------------------------------------------
  464. ##    ask_question() asks a yes/no question.  $default signifies the
  465. ##    default response: 1 = yes, 0 = no.  The default response and
  466. ##    a '?' are appended to the prompt.
  467. ##
  468. sub main'ask_question {
  469.     &set_handler();
  470.     local($prompt, $default) = @_;
  471.     local($tmp, $ret);
  472.     if ($default) { $prompt .= " (\"y\")"; }
  473.     else { $prompt .= " (\"n\")"; };
  474.     while(1) {
  475.     &print_txt("$prompt?  ");
  476.     $tmp = &'get_lc_string();
  477.     $ret = 1, last  if ($tmp =~ /^\s*$/ && $default);
  478.     $ret = 0, last  if ($tmp =~ /^\s*$/ && !$default);
  479.     $ret = 1, last  if ($tmp =~ /^\s*y\s*$/ || $tmp =~ /^\s*yes*\s*$/);
  480.     $ret = 0, last  if ($tmp =~ /^\s*n\s*$/ || $tmp =~ /^\s*no*\s*$/);
  481.     }
  482.     &reset_handler();
  483.     $ret;
  484. }
  485. ##---------------------------------------------------------------------------
  486. ##    get_char_choice() gets a single character response.  Valid
  487. ##    character responses are specified by @chars.  A default can
  488. ##    be specified by $default, and it is the choice if CR is hit.
  489. ##    All whitespaces (except \r and \n) and non-specified chars
  490. ##    are ignored.  This function returns with choice when a valid
  491. ##    character is hit.  Character choices are case-insensitive.
  492. ##
  493. ##    The terminal is put into raw mode for get_char_choice() to
  494. ##    perform its task.  Because of this, SIGINT, SIGQUIT, and
  495. ##    SIGTERM are temporarily ignored until a valid character is
  496. ##    hit.  The original signal handlers are restored before the
  497. ##    functions returns.
  498. ##
  499. sub main'get_char_choice {
  500.     local($default, @chars) = @_;
  501.     local($in, $return);
  502.     local($choices) = join(" ", @chars);
  503.     $choices =~ tr/A-Z/a-z/;
  504.     local($sigint, $sigquit, $sigterm, $sigtstp) =
  505.     ($SIG{'INT'}, $SIG{'QUIT'}, $SIG{'TERM'}, $SIG{'TSTP'});
  506.  
  507.     &'flush(STDOUT);
  508.     $SIG{'INT'} = 'IGNORE'; $SIG{'QUIT'} = 'IGNORE'; $SIG{'TERM'} = 'IGNORE';
  509.     $SIG{'TSTP'} = 'IGNORE';
  510.     system("stty raw -echo");    ## Set terminal in raw mode
  511.     while (1) {
  512.         $in = getc(STDIN);
  513.         $return = $default, last if $default ne "" &&
  514.                     ($in eq "\r" || $in eq "\n");
  515.     next if $in =~ /\s/;
  516.         $in =~ tr/A-Z/a-z/;
  517.     $in =~ s/([\[\]\(\)\.\^\{\}\$\*\?\+\\\|])/\\\1/g;
  518.         $return = $in, last if $choices =~ /$in/;
  519.     }
  520.     system("stty -raw echo");    ## Restore terminal
  521.     print STDOUT "$return\n";    ## Output selection
  522.     $SIG{'INT'} = $sigint;    ## Restore signal handler
  523.     $SIG{'QUIT'} = $sigquit;    ## Restore signal handler
  524.     $SIG{'TERM'} = $sigterm;    ## Restore signal handler
  525.     $SIG{'TSTP'} = $sigtstp;    ## Restore signal handler
  526.     $return;
  527. }
  528. ##---------------------------------------------------------------------------
  529. ##    flush() flushes the buffer of passed in filehandle.  Copied from
  530. ##    "flush.pl".
  531. ##
  532. sub main'flush {
  533.     local($old) = select(shift);
  534.     $| = 1;
  535.     print "";
  536.     $| = 0;
  537.     select($old);
  538. }
  539. ##---------------------------------------------------------------------------
  540. ##    get_later_date() retrieves from STDIN a date later than the
  541. ##    julian date $ljdate.  $prompt is the user prompt and $default
  542. ##    is the default response.  This routine uses the julian date
  543. ##    routines defined in "date.pl".  "date.pl" must be required
  544. ##    somewhere in the Perl program for this routine to work.
  545. ##
  546. sub main'get_later_date {
  547.     local($prompt, $default, $ljdate) = @_;
  548.     local($tmp, $i, $m, $d, $y, $wd);
  549.     while (1) {
  550.     $tmp = &'prompt_user_def($prompt, $default, 1, 0);
  551.     if ($tmp !~ m!^(\d{1,2})[-/](\d{1,2})[-/](\d{2}|\d{4})$!) {
  552.         &'print_error("Incorrect date specification -- $tmp\n",
  553.             "Valid date formats: 02-28-94, 4/1/94, 12-25-1994.");
  554.     }
  555.     else {
  556.         $i = &'jday($1, $2, ($3 > 1900 ? $3 : "19".$3));
  557.         last  if $i > $ljdate;
  558.         ($m, $d, $y, $wd) = &'jdate($ljdate);
  559.         &'print_error("Date must be later than $m/$d/$y.");
  560.     }
  561.     }
  562.     $tmp;
  563. }
  564. ##---------------------------------------------------------------------------
  565. 1;  ## end package
  566.